package com.branches.threads;

import java.util.ArrayList;
import java.util.List;

public class Container {
    private List<Product> products = new ArrayList<>();

    private int idx = 0;

    public synchronized int getIndex() {
        return idx++;
    }
    public void put(Product p) {
        try {
            //sleep不能放在同步代码块里面，因为sleep不会释放锁，
            // 当前线程会一直占有produce线程，直到达到容量，调用wait()方法主动释放锁
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        synchronized (this) {
            while (products.size() > 100) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("put product.." + p.getProductName());
            products.add(p);
            notifyAll();
        }
    }

    public Product take() {
        Product p = null;
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        synchronized (this) {
            //如果容器中没有数据，consumer处于等待状态
            while (products.size() == 0) {
                System.out.println("container is empty,waiting ...");
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //如果有数据，继续consume
            p = products.remove(0);
            System.out.println("take product..." + p.getProductName());
            //唤醒其他所有处于wait()的线程，包括消费者和生产者
            //notify必须放在同步代码块里面
            notifyAll();
        }
        return p;
    }

    public static void main(String[] args) {
        Container container = new Container();
        Thread p1 = new Thread(new Producer(container));
        Thread p2 = new Thread(new Producer(container));
        p1.start();
        p2.start();

        Thread c1 = new Thread(new Consumer(container));
        Thread c2 = new Thread(new Consumer(container));
        Thread c3 = new Thread(new Consumer(container));
        c1.start();
        c2.start();
        c3.start();
    }
}
